package emulator.util.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileHelper {
	public static final int FILE_FORMAT_UNKNOWN = 0; 
	public static final int FILE_FORMAT_RAW = 1;
	public static final int FILE_FORMAT_PRG = 2;
	public static final int FILE_FORMAT_PCVIC = 3;
	public static final int FILE_FORMAT_S20 = 4;
	public static final int FILE_FORMAT_P00 = 5;
	public static final int FILE_FORMAT_CRT = 6;
	
	public static int guessFileFormat(String file_name)
	{
		int file_format = FILE_FORMAT_UNKNOWN;
		File file = new File(file_name);
		if (file.exists() && file.isFile())
		{
			if (hasHeaderMagic(file, P00_HEADER_MAGIC))
				file_format = FILE_FORMAT_P00;
			else if (hasHeaderMagic(file, PCVIC_HEADER_MAGIC))
				file_format = FILE_FORMAT_PCVIC;
			else if (hasHeaderMagic(file, S20_HEADER_MAGIC))
				file_format = FILE_FORMAT_S20;
			else if (hasHeaderMagic(file, CRT_HEADER_MAGIC))
				file_format = FILE_FORMAT_CRT;
			else
			{
				file_format = FILE_FORMAT_RAW;
			    String extension = getFileExtension(file_name).toLowerCase();
				if (extension.equals("prg"))
					file_format = FILE_FORMAT_PRG;
				else if (extension.equals("rom") ||
						 extension.equals("crt"))
					file_format = checkRomFormat(file);
			}
		}
		return file_format;
	}
	
	public static FileInfo getFileInfo(String file_name, int file_format)
	{
		switch (file_format)
		{
			case FILE_FORMAT_RAW: return new FileInfoRaw(file_name);
			case FILE_FORMAT_PRG: return new FileInfoPrg(file_name);
			case FILE_FORMAT_P00: return new FileInfoP00(file_name);
			case FILE_FORMAT_PCVIC: return new FileInfoPcVic(file_name);
		}
		return null;
	}

	static String getFileExtension(String file_name) {
		int dotPos = file_name.lastIndexOf(".");
		String extension = file_name.substring(dotPos+1);
		return extension;
	}

	private static int checkRomFormat(File file) 
	{
		if ((file.length() % 256) == 2)
			return FILE_FORMAT_PRG;
		return FILE_FORMAT_RAW;
	}

	private static boolean hasHeaderMagic(File file, byte [] magic)
	{
		boolean has_magic = false;
		FileInputStream file_stream = null;
		try {
			boolean magic_violated = false;
			file_stream = new FileInputStream(file);
			for (int i = 0; i < magic.length; i++)
			{
				if (file_stream.read() != magic[i])
				{
					magic_violated = true;
					break;
				}
			}
			has_magic = !magic_violated;
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
		finally
		{
			if (file_stream != null)
				try { file_stream.close(); } catch (IOException e) {}
		}
		return has_magic;
	}
	
	static final byte[] PCVIC_HEADER_MAGIC = {
		0x50, 0x43, 0x56, 0x49, 0x43, 0x20, 0x73, 0x79, 
		0x73, 0x74, 0x65, 0x6d, 0x20, 0x73, 0x6e, 0x61,
		0x70, 0x73, 0x68, 0x6f, 0x74, 0x00 };
		static final byte[] S20_HEADER_MAGIC = {
		0x56, 0x49, 0x43, 0x2d, 0x32, 0x30, 0x20, 0x53,
		0x4e, 0x41, 0x50, 0x53, 0x48, 0x4f, 0x54, 0x00 };
	static final byte[] P00_HEADER_MAGIC = {
		0x43, 0x36, 0x34, 0x46, 0x69, 0x6C, 0x65, 0x00 };
	static final byte[] CRT_HEADER_MAGIC = {
		0x43, 0x36, 0x34, 0x20, 0x43, 0x41, 0x52, 0x54,
		0x52, 0x49, 0x44, 0x47, 0x45, 0x20, 0x20, 0x20 };
	
}
